import axios, { AxiosError, type AxiosInstance, type AxiosRequestConfig } from 'axios'
import { showToast, showLoadingToast, closeToast } from 'vant'
import _ from 'underscore'
import { ResultEnum } from '@/enums/http-enum'

// 默认请求配置项
const defaultConfig: AxiosRequestConfig = {
  // 基准地址
  baseURL: 'https://m.maizuo.com',
  // 超时时间，单位是 ms
  timeout: 1000 * 10
}

const addKey = (url: string, code: string) => {
  const tmp = url.split('?')
  const h = tmp[0]
  const p = new URLSearchParams(tmp[1])
  // 增加code属性
  p.append('code', code)
  // 增加k属性
  p.append('k', '' + _.random(0, 10000000))
  return [h, p.toString()].join('?')
}

class HttpRequest {
  server: AxiosInstance

  constructor(config: AxiosRequestConfig) {
    // 创建一个 axios 的实例
    this.server = axios.create(config)

    /**
     * 请求拦截器
     *    客户端发送请求 -> [请求拦截器] -> 服务器
     */
    this.server.interceptors.request.use(
      (config) => {
        // 开始 loading
        config.loading && showLoadingToast({ duration: 0 })

        config.url = addKey(config.url!, config.headers['X-Host'])
        return config
      },
      (error) => {
        return Promise.reject(error)
      }
    )

    /**
     * 响应拦截器
     *    服务器换返回信息 -> [拦截统一处理] -> 客户端JS获取到信息
     */
    this.server.interceptors.response.use(
      (response) => {
        // 获取接口的返回值
        const result = response.data
        // config - 请求配置对象
        const { config } = response

        // 关闭 loading
        config.loading && closeToast()

        // 业务状态码判断
        if (result.status !== ResultEnum.SUCCESS) {
          // 请求时，没有设置 toast ，让其默认值为 true
          config.toast ?? (config.toast = true)
          config.toast && showToast(result.msg)

          return Promise.reject(new Error(result.msg))
        }

        return result.data
      },
      (error: AxiosError) => {
        const { config } = error
        // 关闭 loading
        config?.loading && closeToast()

        // TODO 根据不同的http状态码做不同的业务逻辑处理
        return Promise.reject(error)
      }
    )
  }

  get<T = unknown>(code: string, params: object = {}, config: object = {}): Promise<T> {
    return this.server.get('/gateway', {
      ...config,
      params,
      headers: {
        'X-Host': code
      }
    })
  }

  post<T = unknown>(code: string, params: object, config: object = {}): Promise<T> {
    return this.server.post('/gateway', params, {
      ...config,
      headers: {
        'X-Host': code
      }
    })
  }
}

export default new HttpRequest(defaultConfig)
